#pragma once

// class declarations
class CogSymbol;
class CogProduction;
class CogProductionPool; // pointer only
class CogGrammar; // pointer only

// -----

#include "CogBase.h"

// ------------------------------------------------------------------------------------------

typedef uint32_t CogSymbolFlag;
const CogSymbolFlag COGSF_NONE = 0x00000000;
const CogSymbolFlag COGSF_TERMINAL = 0x00000001;
const CogSymbolFlag COGSF_CONST = 0x00000002;
const CogSymbolFlag COGSF_STARTING = 0x00000004;
const CogSymbolFlag COGSF_EVAL = 0x00000008;
const CogSymbolFlag COGSF_TEMPLATE = 0x00000020;
const CogSymbolFlag COGSF_ANY = 0xFFFFFFFF;

// -----

class CogSymbol
{
public:
	CogSymbol(uint32_t _id = 0, CogSymbolFlag _flag = COGSF_NONE, CogProductionPool* _pPool = NULL, CogProduction* _pRule = NULL)
	: id(_id),
      flag(_flag),
	  pPool(_pPool),
      pRule(_pRule)
	{
	}

	void clear()
	{
		id = 0;
		flag = COGSF_NONE;
		pPool = NULL;
		pRule = NULL;
	}

	// data:
	uint32_t id;
	CogSymbolFlag flag;
	CogProductionPool* pPool;
	CogProduction* pRule;
};

// ------------------------------------------------------------------------------------------

class CogProduction
{
public:
	CogProduction(uint32_t _id = 0, CogSymbolFlag _flag = COGSF_NONE, CogProductionPool* _pPool = NULL, CogProduction* _pRule = NULL, uint32_t _generation = 0)
	: lhs(_id, _flag, _pPool, _pRule),
      usedBy(0),
      ntSize(0),
      generation(_generation)
    {
    }

	void computeSize();
	void use();
	void use(size_t times);
	void unuse();

	bool fromStream(istream &in, CogGrammar* pGram);
	void toStream(ostream &out, const CogGrammar* pGram) const;
	void expandToStream(ostream &out, const CogGrammar* pGram, bool printHeader) const;

	// definition:
	CogSymbol lhs;
	vector<CogSymbol> rhs;

	// compute cache:
	char* pCache;

	// statistics:
	uint32_t usedBy;
	uint32_t ntSize;
	uint32_t generation;
};

// ------------------------------------------------------------------------------------------
